package com.ybear.ybcomponent.widget

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.annotation.Px
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import com.ybear.ybcomponent.Utils
import kotlin.math.abs

/**
 * LinearLayout - 悬浮版
 */
@SuppressLint("ClickableViewAccessibility")
class FloatingLayout : LinearLayout {


    private var bubbleText: String? = null
    private var floatingBackgroundDrawable: Drawable? = null
    private var floatingBackgroundDrawableRtl: Drawable? = null
    private var bubbleBackgroundWidth: Int = 0
    private var bubbleBackgroundHeight: Int = 0
    private var bubblePaddingRect: Rect = Rect()

    private var initialX = 0f
    private var initialY = 0f
    private var dX = 0f
    private var dY = 0f
    private var isDragging = false

    private var onTouchListener: OnTouchListener? = null
    private var onClickListener: OnClickListener? = null

    // 添加文本 TextView
    private val bubbleTextView: TextView by lazy {
        TextView( context ).apply {
            layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )
            setTextColor( Color.WHITE )
            gravity = Gravity.CENTER
            isVisible = false
        }
    }

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes)

    init {
        orientation = VERTICAL
        gravity = Gravity.TOP or Gravity.END

        super.setOnTouchListener { view, event ->
            onTouchListener?.onTouch(view, event)
            when ( event.actionMasked ) {
                MotionEvent.ACTION_DOWN -> {
                    isDragging = true
                    initialX = event.rawX
                    initialY = event.rawY
                    dX = view.x - initialX
                    if( isRTL() ) dX -= view.width
                    dY = view.y - initialY
                    return@setOnTouchListener true
                }
                MotionEvent.ACTION_MOVE -> {
                    if ( isDragging ) {
                        val parentHeight = (parent as View).height
                        val x = event.rawX + dX
                        val y = event.rawY + dY
                        // 适配阿拉伯方向
                        view.x = if( isRTL() ) view.width + x else x
                        // 限制 y 值
                        view.y = y.coerceIn( 0f, ( parentHeight - view.height ).toFloat() )
                        //拖动时隐藏气泡
                        hideBubble()
                        return@setOnTouchListener true
                    }
                }
                MotionEvent.ACTION_UP -> {
                    isDragging = false
                    // 吸附效果
                    snapToEdge( view )
                    // 如果没有移动，触发点击事件
                    if ( abs( event.rawX - initialX ) < 5 && abs( event.rawY - initialY ) < 5 ) {
                        view.performClick()
                    }
                    return@setOnTouchListener true
                }
            }
            return@setOnTouchListener false
        }
    }

    override fun performClick(): Boolean {
        onClickListener?.onClick( this )
        return super.performClick()
    }

    /**
     * 松开拖拽后的吸附效果
     */
    private fun snapToEdge(view: View) {
        val parentWidth = (parent as View).width
        val halfWidth = parentWidth / 2
        val childCenterX = view.x + view.width / 2
        val targetX = if ( childCenterX > halfWidth )
            // 吸附到右侧
            parentWidth - view.width
         else
             // 吸附到左侧
            0

        view.animate()
            .x(targetX.toFloat())
            .setDuration(200)
            .start()
    }

    /**
     * 重写Touch事件
     */
    override fun setOnTouchListener(l: OnTouchListener?) { onTouchListener = l }

    /**
     * 重写点击事件
     */
    override fun setOnClickListener(l: OnClickListener?) { onClickListener = l }

    // 创建 Builder 对象
    fun createBubble(): BubbleBuilder {
        return BubbleBuilder(this)
    }

    // Builder 类
    inner class BubbleBuilder(private val floatingLayout: FloatingLayout) {
        /**
         * 设置气泡背景
         */
        @JvmOverloads
        fun background(@Px width: Int,
                       @Px height: Int,
                       drawable: Drawable,
                       drawableRtl: Drawable? = null
        ): BubbleBuilder {
            floatingLayout.floatingBackgroundDrawable = drawable
            floatingLayout.floatingBackgroundDrawableRtl = drawableRtl
            floatingLayout.bubbleBackgroundWidth = width.toPx()
            floatingLayout.bubbleBackgroundHeight = height.toPx()
            return this
        }

        /**
         * 设置背景
         */
        @JvmOverloads
        fun background(@Px width: Int,
                       @Px height: Int,
                       @DrawableRes resId: Int,
                       @DrawableRes resIdRtl: Int? = 0
        ): BubbleBuilder {
            val drawable = floatingLayout.toDrawable( resId ) ?: return this
            return background(
                width,
                height,
                drawable,
                if( resIdRtl == null || resIdRtl == 0 ) null else toDrawable( resIdRtl )
            )
        }

        /**
         * 设置间距
         */
        fun paddingPx(@Px start: Int, @Px top: Int, @Px end: Int, @Px bottom: Int): BubbleBuilder {
            bubblePaddingRect.set( start.toPx(), top.toPx(), end.toPx(), bottom.toPx() )
            return this
        }

        /**
         * 设置间距
         */
        fun paddingPx(@Px horizontal: Int, @Px vertical: Int) : BubbleBuilder {
            return paddingPx( horizontal, vertical, horizontal, vertical )
        }

        // 构建 PopupWindow
        fun build(): FloatingLayout {
            //间距
            bubbleTextView.setPaddingRelative(
                bubblePaddingRect.left, bubblePaddingRect.top,
                bubblePaddingRect.right, bubblePaddingRect.bottom
            )
            //背景
            bubbleTextView.background = if( isRTL() )
                floatingLayout.floatingBackgroundDrawableRtl
            else
                floatingLayout.floatingBackgroundDrawable
            //宽高
            bubbleTextView.layoutParams.apply {
                width = floatingLayout.bubbleBackgroundWidth
                height = ViewGroup.LayoutParams.WRAP_CONTENT
                bubbleTextView.layoutParams = this
            }
            //最小高度
            bubbleTextView.minimumHeight = floatingLayout.bubbleBackgroundHeight
            //添加布局
            bubbleTextView.layoutParams.apply {
                if( width != 0 && height != 0 ) floatingLayout.addView( bubbleTextView, 0 )
            }
            return floatingLayout
        }

        // 设置气泡文本
        @JvmOverloads
        fun bubbleText(text: String,
                       gravity: Int = Gravity.START or Gravity.TOP,
                       textSize: Float = 12F,
                       textColor: Int = Color.WHITE
        ): BubbleBuilder {
            floatingLayout.bubbleText = text
            floatingLayout.bubbleTextView.apply {
                setTextColor(textColor)
                setTextSize(textSize)
                this.gravity = gravity
                this.text = text
            }
            return this
        }

        /**
         * 获取气泡控件
         */
        fun getBubbleTextView() : TextView { return bubbleTextView }
    }

    // 显示气泡
    fun showBubble() {
        if( bubbleTextView.isVisible ) return
        bubbleTextView.isVisible = true
        bubbleTextView.measure( 0, 0 )
        y -= bubbleTextView.measuredHeight
        post { snapToEdge( this ) }
    }

    /**
     * 隐藏气泡
     */
    fun hideBubble() {
        if( !bubbleTextView.isVisible ) return
        bubbleTextView.isVisible = false
        bubbleTextView.measure( 0, 0 )
        y += bubbleTextView.measuredHeight
        post { snapToEdge( this ) }
    }

    private fun isRTL(): Boolean {
        return layoutDirection == View.LAYOUT_DIRECTION_RTL
    }

    private fun Int.toPx(): Int {
        return Utils.dp2Px( context, this.toFloat() ).toInt()
    }

    private fun toDrawable(@DrawableRes resId: Int): Drawable? {
        return ContextCompat.getDrawable( context, resId )
    }
}